<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Thist</title>
</head>

<body>
    <script>
        ;(function () {
            return false;
            // 1. 作为对象的方法调用
            var obj = {
                a: 1,
                getA: function () {
                    alert(this === obj); // 输出：true
                    alert(this.a); // 输出: 1
                }
            };
            obj.getA();
        })();

        ;(function () {
            return false;
            // 2. 作为普通函数调用
            window.name = 'globalName';

            /* var getName = function () {
                return this.name;
            };
            console.log(getName()); // 输出：globalName */

            var myObject = {
                name: 'sven',
                getName: function () {
                    return this.name;
                }
            };
            var getName = myObject.getName;
            console.log(getName()); // globalName 
        })();

        ;(function () {
            return false;
            // 3. 构造器调用

            /* var MyClass = function () {
                this.name = 'sven';
            };
            var obj = new MyClass();
            alert(obj.name); // 输出：sven */

            // 如果构造器显式地返回了一个 object 类型的对象，那么此次运算结果最终会返回这个对象，而不是我们之前期待的 this

            /* var MyClass = function () {
                this.name = 'sven';
                return { // 显式地返回一个对象
                    name: 'anne'
                }
            };
            var obj = new MyClass();
            alert(obj.name); // 输出：anne */

            // 如果构造器不显式地返回任何数据，或者是返回一个非对象类型的数据，就不会造成上述问题：

            var MyClass = function () {
                this.name = 'sven'
                return 'anne'; // 返回 string 类型
            };
            var obj = new MyClass();
            alert(obj.name); // 输出：sven
        })();

        
        ;(function () {
            // 1. Function.prototype.call 或 Function.prototype.apply 调用
            // 跟普通的函数调用相比，用 Function.prototype.call 或 Function.prototype.apply 可以动态地改变传入函数的 this：
            var obj1 = {
                name: 'sven',
                getName: function () {
                    return this.name;
                }
            };
            var obj2 = {
                name: 'anne'
            };
            console.log(obj1.getName()); // 输出: sven
            console.log(obj1.getName.call(obj2)); // 输出：anne 

        })();
        
    </script>
</body>

</html>